<template>
  <div class="filter-search-content">
    <el-form :inline="true" class="demo-form-inline">
      <div class="left">
        <!-- 筛选选项列表 -->
        <el-form-item v-for="item in filtersOptions.filters" :key="item.prop" :label-width="item.width" :label="labelSet(item.label)">
          <!-- 普通input框输入 -->
          <template v-if="item.inputType === 'input'">
            <el-input
              v-model="propsParams.params[item.prop]"
              v-bind="item.attrs"
              :clearable="isClearable(item.clearable)"
              :placeholder="placeholderSet(item)"
              :size="item.size || 'small'"
            ></el-input>
          </template>
          <!-- 手机号码input框输入 -->
          <template v-if="item.inputType === 'telInput'">
            <el-input
              onkeyup="this.value = this.value.replace(/[^\d.]/g,'');"
              v-model="propsParams.params[item.prop]"
              v-bind="item.attrs"
              :clearable="isClearable(item.clearable)"
              :placeholder="placeholderSet(item)"
              :size="item.size || 'small'"
            ></el-input>
          </template>
          <!-- 选择框 -->
          <template v-if="item.inputType === 'select'">
            <el-select
              v-model="propsParams.params[item.prop]"
              :clearable="isClearable(item.clearable)"
              :collapse-tags="item.multiple ? true : false"
              :multiple="!!item.multiple"
              popper-append-to-body
              :placeholder="placeholderSet(item)"
              :filterable="!!item.filterable"
              :size="item.size || 'small'"
            >
              <el-option v-for="item in item.options" :key="item.value" :label="item.label" :value="item.value"></el-option>
            </el-select>
          </template>
          <!-- 级联选择  value,label 必传-->
          <template v-if="item.inputType === 'cascader'">
            <el-cascader
              v-model="propsParams.params[item.prop]"
              :placeholder="item.placeholder || '请选择' + item.label"
              :options="item.options"
              :props="{ checkStrictly: true, value: item.props.value, label: item.props.label }"
              clearable
              :size="item.size || 'small'"
            ></el-cascader>
          </template>
          <!-- 日期选择 -->
          <template v-if="item.inputType === 'datePicker'">
            <el-date-picker
              v-model="propsParams.params[item.prop]"
              :clearable="isClearable(item.clearable)"
              :type="item.type || 'date'"
              :start-placeholder="item['startPlaceholder']"
              :end-placeholder="item['endPlaceholder']"
              :placeholder="placeholderSet(item)"
              :format="item.format"
              :value-format="item.format"
              :size="item.size || 'small'"
            />
          </template>
        </el-form-item>
        <slot></slot>
      </div>
      <!-- 其它按钮列表 -->
      <div class="right" v-if="clickBtns.length > 0">
        <el-form-item v-for="item in clickBtns" :key="item._id">
          <el-button
            v-if="!item.hidden"
            @click="handelClick(item, clickBtns)"
            :class="item.class"
            :size="item.size || 'small'"
            :type="item.type"
            :icon="item.icon"
            v-bind="item.attrs"
            :style="item.style"
          >
            {{ item.label }}
          </el-button>
        </el-form-item>
      </div>
    </el-form>
  </div>
</template>

<script lang="ts">
  import { ref, reactive, watch, watchEffect, defineComponent, computed, toRefs, unref } from 'vue'
  import { Utils } from '@/utils'
  interface btnPropsItem {
    hiddenQueryBtn: false
    queryBtnLabel: '搜索'
    queryBtnClass: []
    queryBtnSize: 'medium'
    queryBtnType: ''
    list: []
  }

  interface formItemProp {
    inputType: string
    prop: string
    type?: string
    label: string
    placeholder?: string
    clearable: boolean
    options?: Array<any>
    format?: any
    width?: number
    attrs?: any
    clearQuery?: boolean
  }

  interface Props {
    modelValue?: any
    colonSuffix: boolean
    filtersList: Array<any>
    btnProps: btnPropsItem
    [key: string]: any
  }

  interface PropsParams {
    params: any

    [key: string]: any
  }

  interface clickItem {
    type: string
    _id: string | number
    emit: string
    isClick?: boolean
    style?: any
    styless?: Array<any>
  }

  export default defineComponent({
    name: 'FilterSearch',
    props: {
      //首次是否执行查询
      immediateQuery: {
        type: Boolean,
        default: true
      },
      // label是否添加冒号后缀
      colonSuffix: {
        type: Boolean,
        default: true
      },
      filtersList: {
        type: Array,
        default: () => []
      },
      btnProps: {
        type: Object,
        default: () => ({
          hiddenQueryBtn: false,
          queryBtnLabel: '搜索',
          queryBtnClass: [],
          queryBtnSize: 'medium',
          queryBtnType: '',
          list: []
        })
      }
    },
    setup(props, { emit, attrs }) {
      const filtersOptions = reactive({ filters: props.filtersList })
      const watchDeep = { deep: true }
      const propsParams = reactive<PropsParams>({ params: {} })
      // const modelValues =
      //按钮列表
      const clickBtns = computed(() => {
        let btns: Array<any> = []
        if (Array.isArray(props.btnProps)) {
          btns = props.btnProps
        } else {
          btns = props.btnProps?.list ? props.btnProps?.list : []
        }
        btns.map((btn) => ({
          ...btn,
          emit: btn.emit ? btn.emit : 'handelClick',
          _id: btn.id ? btn.id || btn._id : Utils.toAnyString()
        }))
        return btns
      })
      // 按钮事件
      const handelClick = (item: clickItem, otherBtns: any) => {
        let emitName = item.emit
        // 查询
        if (emitName === 'query') {
          !attrs.onQuery && (emitName = '')
        }
        //重置
        if (emitName === 'reset') {
          //未传 onReset
          !attrs.onReset && (emitName = '')
          propsParams.params = handelVerificationProp(filtersOptions.filters)
        }
        //按钮切换
        if (item.styless && !item.isClick) {
          otherBtns
            .filter((j: clickItem) => j.styless)
            .map((j: clickItem) => {
              j.isClick = !j.isClick
              if (j.isClick) {
                j.style = j.styless && j.styless[0]
              } else {
                j.style = j.styless && j.styless[1]
              }
            })
        }

        emit(emitName || 'handelClick', { ...item, query: { ...propsParams.params } }, otherBtns)
      }

      // 验证提示 是否存在prop属性，并且设置prop 和 value
      const handelVerificationProp = (data: any) => {
        const result: any = {}
        if (!data || !Array.isArray(data) || data.length < 1) {
          console.warn('filtersOptions参数错误')
          return
        }
        data.map((item, index: number) => {
          if (!item.prop) console.warn(`${data[index].label}属性值没有prop参数`)
          if (item.defaultValue) {
            result[item.prop] = item.defaultValue
          } else {
            result[item.prop] = item.value || ''
          }
        })
        return JSON.parse(JSON.stringify(result))
      }
      /**
       * 一进来默认会触发emit为query的 回调事件
       */
      let flag = unref(clickBtns).filter((item: clickItem) => item.emit === 'query')
      if (flag.length > 0 && props.immediateQuery) {
        handelClick(flag[0], clickBtns)
      }

      propsParams.params = handelVerificationProp(filtersOptions.filters)

      const isClearable = (clearable: unknown) => {
        if (clearable === true || clearable === undefined) return true
        return false
      }

      // 监听传入数据变化（第一次进来初始化时）
      watch(
        () => filtersOptions.filters,
        () => {
          propsParams.params = handelVerificationProp(filtersOptions.filters)
        },
        watchDeep
      )

      watchEffect(() => {
        emit('update:modelValue', propsParams.params)
      })
      /**
       * 标题设置
       * label: string 标题
       * needType: boolean 是否需要冒号 defaultValue： true
       */
      const labelSet = (label: string, needType: boolean = true): string => {
        let flag = label.indexOf(':') > 0 || label.indexOf('：') > 0
        if (needType) {
          if (flag) {
            return label
          } else {
            return label + '：'
          }
        } else {
          if (flag) {
            return label.slice(0, label.length - 1)
          } else {
            return label
          }
        }
      }
      /**
       * placeholder设置
       */
      const placeholderSet = (e: formItemProp): string => {
        switch (e.inputType) {
          case 'input':
            return '请输入' + labelSet(e.label, false)
          case 'telInput':
            return '请输入' + labelSet(e.label, false)
          case 'select':
            return '请选择' + labelSet(e.label, false)
          default:
            return '请选择' + labelSet(e.label, false)
        }
      }
      return {
        filtersOptions,
        propsParams,
        handelClick,
        isClearable,
        clickBtns,
        handelVerificationProp,
        placeholderSet,
        labelSet
      }
    }
  })
</script>

<style lang="scss" scoped>
  .demo-form-inline {
    display: flex;
    flex-wrap: wrap;
    .left {
    }

    .right {
      //重置按钮
      .reset-btn {
        background: #d5e0e5;
        border: 1px solid #d9d9d9;
        color: black;
      }
      .el-button--default:hover {
        opacity: 0.7;
      }
    }
    ::v-deep(.el-button) {
      padding: 8px 20px;
      font-size: 14px;
    }
  }

  .filter-search-content {
    ::v-deep .el-form-item {
      margin-bottom: 20px;
      margin-right: 15px;
    }

    ::v-deep .el-form-item__label {
      padding: 0;
      color: #666;
    }

    ::v-deep .el-form-item__content {
      .el-input {
        width: 200px;
      }
    }

    ::v-deep input::-webkit-outer-spin-button,
    ::v-deep input::-webkit-inner-spin-button {
      -webkit-appearance: none !important;
    }

    ::v-deep input[type='number'] {
      -moz-appearance: textfield;
    }
  }
</style>
